﻿using System;
using System.Collections.Generic;
using System.Text;
using System.IO;
using Lon.IO;
using Lon.DataStore;
using Lon.Util;

namespace Lon.Server
{
   
 
    /// <summary>
    /// 网络节点
    /// 可能为站机也可能是终端、服务器
    /// </summary>
    public  class NetNode
    {
        private String dbm;
        /// <summary>
        /// 服务器对外接口Id
        /// </summary>
        public int InferfaceId;
        public event EventHandler<RawDataUpdateEventArgs> DataUpdateHandler;
        public String Dbm
        {
            get { return dbm; }
            set { dbm = value; }
        }

        private int id;

        public int Id
        {
            get { return id; }
            set 
            { 
                id = value;
                if (String.IsNullOrEmpty(dbm))
                {
                   this.dbm=DbmHelper.IdToDbm(id);
                }
            }
        }

        private String ip;
        public String Ip
        {
            get { return ip; }
            set { ip = value; }
        }
        private IFrontServer parentServer;
        /// <summary>
        /// 以后改为在配置文件中动态加载
        /// </summary>
        byte[] AnalogTypeTable =
            new byte[]{
                0x10,0x11,0x12,0x13,0x14,0x15,0x16,0x17,0x18,0x19,0x1A,0x1B,0x1C,0x1E,0x1F,
                0x20,0x21,0x22,0x23,0x24,0x25,0x26,0x27,0x28,0x29,0x2A,0x2B,0x2C,0x2E,0x2F,
                0x30,0x31,0x32,0x33,0x34,0x35,0x36,0x37,0x38,0x39,0x3A,0x3B,0x3C,0x3E,0x3F,
                0x40,0x41,0x42,0x43,0x44,0x45,0x46,0x47,0x48,0x49,0x4A,0x4B,0x4C,0x4E,0x4F,
                0x50,0x51,0x52,0x53,0x54,0x55,0x56,0x57,0x58,0x59,0x5A,0x5B,0x5C,0x5E,0x5F,
                0x60,0x61,0x62,0x63,0x64,0x65,0x66,0x67,0x68,0x69,0x6A,0x6B,0x6C,0x6E,0x6F,
                0x70,0x71,0x72,0x73,0x74,0x75,0x76,0x77,0x78,0x79,0x7A,0x7B,0x7C,0x7E,0x7F,
                0x80,0x81,0x82,0x83,0x84,0x85,0x86,0x87,0x88,0x89,0x8A,0x8B,0x8C,0x8E,0x8F,
                0x90,0x91,0x92,0x93,0x94,0x95,0x96,0x97,0x98,0x99,0x9A,0x9B,0x9C,0x9E,0x9F,
                0xA0,0xA1,0xA2,0xA3,0xA4,0xA5,0xA6,0xA7,0xA8,0xA9,0xAA,0xAB,0xAC,0xAE,0xAF,
                0xB0,0xB1,0xB2,0xB3,0xB4,0xB5,0xB6,0xB7,0xB8,0xB9,0xBA,0xBB,0xBC,0xBE,0xBF,
                0xC0,0xC1,0xC2,0xC3,0xC4,0xC5,0xC6,0xC7,0xC8,0xC9,0xCA,0xCB,0xCC,0xCE,0xCF,
                0xD0,0xD1,0xD2,0xD3,0xD4,0xD5,0xD6,0xD7,0xD8,0xD9,0xDA,0xDB,0xDC,0xDE,0xDF,
                0xE0,0xE1,0xE2,0xE3,0xE4,0xE5,0xE6,0xE7,0xE8,0xE9,0xEA,0xEB,0xEC,0xEE,0xEF,
                0xF0,0xF1,0xF2,0xF3,0xF4,0xF5,0xF6,0xF7,0xF8,0xF9,0xFA,0xFB,0xFC,0xFE/*,0xFF,*/
           
            };
        public IFrontServer ParentServer
        {
            get { return parentServer; }
            set { parentServer = value; }
        }
        protected static IDataAccessService dataStoreModule=DataAccessSeriveFactory.GetService(null);
        public EventHandler<ConnectStatusChangeEventArgs> ConnectStatusChangeHandler;
        private DateTime lastStateTime;
        private bool connectedState=false;
        public  bool IsTJWX = false;

        private NodeType nodeType;

        public NodeType NodeType
        {
            get { return nodeType; }
            set { nodeType = value; }
        }

        private String name;
        public String Name
        {
            get { return name; }
            set { name = value; }
        }

  
      
        public bool ConnectedState
        {
            get
            { 
                return connectedState;      
            }
            set
            {
                lock (this)
                {   
                  
                    if (connectedState == value) return;
                    LogConnentState(value);
                    connectedState = value;
                    if (connectedState == false) return;
                
                }
            }
           
        }
        private void DoStatusChangeHandle(bool status)
        {
            EventHandler<ConnectStatusChangeEventArgs> temp = ConnectStatusChangeHandler;
            if (temp == null) return;
            temp(this,new ConnectStatusChangeEventArgs(status));
        }

        private void LogConnentState(bool p)
        {
            dataStoreModule.SaveConnectLog(DateTimeHelper.DateTime2UnixTime(DateTime.Now), this.Id, this.Name, this.dbm, p ? "连接正常" : "连接断开");
        }

        public DateTime LastStateTime
        {
            get { return lastStateTime; }
        }

     
        public void SendDataFrame(DataFrame df)
        {
            if (this.parentServer == null) return;
            if (this.ConnectedState == false) return;
            DataFrame newDf = df.Clone();
            newDf.DstId = this.Id;
            this.RealSend(newDf);
         
            
        }

        void RealSend(DataFrame df)
        {
            DataLog(df, Lon.Data.DataDir.Transmit);
            this.parentServer.SendMessage(df);
        }
        private List<NetRawDataRec> rawDataRecs = new List<NetRawDataRec>(200);
        private void DataLog(DataFrame df, Lon.Data.DataDir dir)
        {
            if (df.DataFrameFlag == DataFrameFlag.Heartbeat) // 不显示心跳帧   
            {
                return;
            }
            NetRawDataRec rec = new NetRawDataRec(df, dir);

            lock (this.rawDataRecs)
            {
                if (this.rawDataRecs.Count > 200)
                {
                    this.rawDataRecs.RemoveAt(0);
                }
                this.rawDataRecs.Add(rec);
            }
            this.DoDataUpdateHandler(rec);
        }
        private void DoDataUpdateHandler(NetRawDataRec rec)
        {
            EventHandler<RawDataUpdateEventArgs> temp = DataUpdateHandler;
            if (temp == null) return;
            RawDataUpdateEventArgs args = new RawDataUpdateEventArgs(rec);
            temp(this, args);
        }
        public    DataFrame AllKglFrame = null;
        public  DataFrame AllChangeKglFrame = null;

		public bool lastDayReportQueried=false;
		
		
		

        public bool QueryDayReport(DateTime dt)
        {
            bool res = true;
            if (this.ConnectedState == false) return false;
			for(int i=0;i<AnalogTypeTable.Length;i++)
			{
                if (QueryDayReport(dt, AnalogTypeTable[i]) == false)
                {
                    res=false;
                }
			}
            return res;
              
        }

        private bool QueryDayReport(DateTime dt, byte p)
        {
            try
            {
                if (this.ConnectedState == false) return false;
                byte[] queryCmd = new byte[5];
                MemoryStream ms = new MemoryStream();
                BinaryWriter br = new BinaryWriter(ms);
                br.Write((byte)0x41);
                br.Write(DateTimeHelper.DateTime2UnixTime(dt));
                DataFrame df = new DataFrame(this.Id, InferfaceId, DataDir.StationData, false, true, false, 0x13, p, queryCmd);
                this.ParentServer.SendMessage(df);
                return true;
            }
            catch
            {
                return false;
            }

          
           
         
        }

        /// <summary>
        /// 饥饿度计数.当饥饿度高的一定状态时
        /// 节点会被饿死,即连接状态失败
        /// </summary>
        int hungryCount = 0;

        /// <summary>
        /// 最大饥饿指数
        /// </summary>
        int hungryMax = 70;

        internal void Feed()
        {
            hungryCount = 0;
            lastStateTime = DateTime.Now;
            if (this.connectedState == false)
            {
                this.connectedState = true;
            }
        }

        /// <summary>
        /// 周期检查函数
        /// </summary>
        public void PeriodCheck()
        {
            if (this.connectedState == false)
            {
                return;
            }
            hungryCount++;
            if (hungryCount >= hungryMax)
            {
                this.connectedState = false;
            }
 
        }
       
    }

   

    public class VerMessage
    {
        public DataFrame lastUpdateFrame=null;
        /// <summary>
        /// 机器名
        /// </summary>
        public String ComputorName { get; set; }
        /// <summary>
        /// 操作系统版本
        /// </summary>
        public String SystemVer { get; set; }
        /// <summary>
        /// 软件版本
        /// </summary>
        public String SoftVer { get; set; }



    }


    

    public abstract class DataFrameParser
    {
        protected byte funCode;
        public abstract byte FunCode{get;}
        public abstract void Parse(DataFrame df);    
    }

    

    
 
}
